home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xtartan-2.0 / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-24  |  6.5 KB  |  308 lines

  1. /* draw.c - the routines which actually do the tartan drawing
  2.  * by Jim McBeath (jimmc@hisoft.uucp)
  3.  *
  4.  *  7.Jan.88  jimmc  Initial definition (X10)
  5.  * 24.Oct.89  jimmc  Convert to X11, Xt; general restructuring
  6.  */
  7.  
  8. #include <X11/Intrinsic.h>
  9. #include <stdio.h>
  10. #include "tartan.h"
  11.  
  12. extern TartanInfo *curtartan;
  13. extern Display *TDisplay;
  14. extern Screen *TScreen;
  15. extern Drawable TDrawable;
  16. extern Window TWindow;
  17. extern GC Tgc;
  18.  
  19. static int scale;
  20. static int lwidth;
  21. static int drwheight;
  22.  
  23. setScaleWidth(s,w)
  24. int s,w;
  25. {
  26.     scale = s;
  27.     lwidth = w;
  28. }
  29.  
  30. changeScale(s)
  31. char *s;
  32. {
  33.     int newscale;
  34.  
  35.     if (s[0]=='+')
  36.         newscale = scale + atoi(s+1);
  37.     else if (s[0]=='-')
  38.         newscale = scale - atoi(s+1);
  39.     else
  40.         newscale = atoi(s);
  41.     if (newscale<=0) {
  42.         Bell();
  43.         return;
  44.     }
  45.     scale = newscale;
  46.     redraw();
  47.     
  48. }
  49.  
  50. int getScale() {
  51.     return scale;
  52. }
  53.  
  54. changeWidth(s)
  55. char *s;
  56. {
  57.     int newlwidth;
  58.  
  59.     if (s[0]=='+')
  60.         newlwidth = lwidth + atoi(s+1);
  61.     else if (s[0]=='-')
  62.         newlwidth = lwidth - atoi(s+1);
  63.     else
  64.         newlwidth = atoi(s);
  65.     if (newlwidth<=0) {
  66.         Bell();
  67.         return;
  68.     }
  69.     lwidth = newlwidth;
  70.     redraw();
  71.     
  72. }
  73.  
  74. int getWidth() {
  75.     return lwidth;
  76. }
  77.  
  78. DrawTartan(rx,ry,rw,rh)        /* draws the currently selected tartan */
  79. int rx,ry,rw,rh;    /* region to draw in */
  80. {
  81.     TartanInfo *ti;
  82.     Sinfo *si;
  83.     int bgpixel;
  84.  
  85.     ti = curtartan;
  86.     if (!ti) return;    /* nothing to draw */
  87.     bgpixel = colorPixel(ti->hstripes.slist[0].color);
  88.     FillBox(rx,ry,rw,rh,bgpixel,SOLID);
  89.     /* fill region with background */
  90.     si = &(ti->hstripes);    /* do the horizontal stripes */
  91.     FillStripes(ry,rh,rx,rw,si,0);
  92.     si = &(ti->vstripes);    /* do the vertical stripes */
  93.     if (si->flags & HVSAME)
  94.         si = &(ti->hstripes);    /* vertical same as horizontal */
  95.     FillStripes(rx,rw,ry,rh,si,1);
  96. }
  97.  
  98. FillStripes(org,size,othorg,othsize,si,vflag)
  99. int org,size;        /* origin and size in direction of interest */
  100. int othorg, othsize;    /* origin and size in the other direction */
  101. Sinfo *si;        /* the stripe info */
  102. int vflag;        /* set for vertical stripes, clear for horizontal */
  103. {
  104.     int corg;        /* current x or y origin */
  105.     int n;
  106.     int delta;
  107.     S1info *s1i;
  108.     int sw;
  109.     int sflag;
  110.     int pixel;
  111.  
  112.     corg = 0;        /* start at the top/left of the screen */
  113.     n = 0;            /* start with the first stripe */
  114.     delta = 1;
  115.     sflag = vflag?HSTRIPE:VSTRIPE;
  116.     while (corg<org+size) {    /* repeat the pattern */
  117.         s1i = si->slist+n;
  118.         sw = s1i->width*scale;
  119.         if (corg+sw>=org) {
  120.             pixel = colorPixel(s1i->color);
  121.             if (vflag) {
  122.                 FillBox(corg,othorg,sw,othsize,
  123.                     pixel, s1i->style|sflag);
  124.             } else {
  125.                 FillBox(othorg,corg,othsize,sw,
  126.                     pixel, s1i->style|sflag);
  127.             }
  128.             /* fill the area with the proper pattern */
  129.         }
  130.         corg += sw;
  131.         n += delta;
  132.         if (n<0) {    /* from counting backwards */
  133.             n = 1;
  134.             delta = 1;
  135.         }
  136.         else if (!si->slist[n].color) {    /* if at the end... */
  137.             if (si->flags & SYM) {
  138.                 if (si->flags & PIVOT2)
  139.                     n -= 3;    /* double-pivot */
  140.                 else
  141.                     n -= 2;    /* single-pivot (normal) */
  142.                 delta = -1;    /* count backwards */
  143.             }
  144.             else n=0;    /* wrap on overflow */
  145.         }
  146.     }
  147. }
  148.  
  149. FillBox(x,y,w,h,pixel,style)
  150. int x,y;    /* origin of box, (0,0) is lower left */
  151. int w,h;    /* size of box */
  152. int pixel;    /* pixel value to use */
  153. int style;    /* what style to draw in */
  154. {
  155.     int nstyle;
  156.     int offset;
  157.     int d;
  158.     int cx, cy;
  159.     int x0,y0,x1,y1;
  160.     int lw;
  161.     int q=0;
  162.  
  163.     XSetForeground(TDisplay,Tgc,pixel);
  164.     y = drwheight-h-y;    /* change to X screen coords */
  165.     offset = (style&HSTRIPE)?1:0;
  166.     if (offset)
  167.         w+=lwidth;
  168.     nstyle = style & ~(HSTRIPE|VSTRIPE);
  169.     if (!nstyle)
  170.         nstyle = ALINES;    /* default style */
  171.     switch (nstyle) {
  172.     case RLINES:    /* same direction as length of stripe */
  173.         nstyle = (style&HSTRIPE)?HLINES:VLINES;
  174.         break;
  175.     case NOP:
  176.         return;        /* no nothing */
  177.     default:
  178.         break;
  179.     }
  180.     switch (nstyle) {
  181.     case SOLID:
  182.         XFillRectangle(TDisplay,TDrawable,Tgc,x,y,w,h);
  183.         break;
  184.     case HLINES:
  185.         cy = (y+lwidth-1)/lwidth;
  186.         cy -= offset^(cy&1);
  187.         cy *= lwidth;
  188.         XSetLineAttributes(TDisplay,Tgc,lwidth==1?0:lwidth,0,0,0);
  189.         for (; cy<y+h; cy+=2*lwidth) {
  190.             XDrawLine(TDisplay,TDrawable,Tgc,x,cy,x+w-1,cy);
  191.         }
  192.         break;
  193.     case VLINES:
  194.         cx = (x+lwidth-1)/lwidth;
  195.         cx -= offset^(cx&1);
  196.         cx *= lwidth;
  197.         XSetLineAttributes(TDisplay,Tgc,lwidth==1?0:lwidth,0,0,0);
  198.         for (; cx<x+w; cx+=2*lwidth) {
  199.             XDrawLine(TDisplay,TDrawable,Tgc,cx,y,cx,y+h-1);
  200.         }
  201.         break;
  202.     case ALINES:
  203.         cx = (x+y+lwidth-1)/lwidth;
  204.         d = -(offset^(cx&1));
  205.         d *= lwidth;
  206.         d += lwidth-1-((x+y+lwidth-1)%lwidth);
  207.         lw = (int)(0.8*((float)(lwidth)));
  208.         XSetLineAttributes(TDisplay,Tgc,lw<=1?0:lw,0,0,0);
  209.         for (; d<w+h-1; d+=2*lwidth) {
  210.             if (d<w) {
  211.                 x0 = x+d;
  212.                 y0 = y;
  213.             } else {
  214.                 x0 = x+(w-q);
  215.                 y0 = y+d-(w-q);
  216.             }
  217.             if (d<h) {
  218.                 x1 = x;
  219.                 y1 = y+d;
  220.             } else {
  221.                 x1 = x+d-(h-q);
  222.                 y1 = y+(h-q);
  223.             }
  224.             XDrawLine(TDisplay,TDrawable,Tgc,x0,y0,x1,y1);
  225.         }
  226.         break;
  227.     default:
  228.         break;    /* should never get here */
  229.     }
  230. }
  231.  
  232. tartanSize(si)
  233. Sinfo *si;
  234. {
  235.     S1info *s1i;
  236.     int w;
  237.  
  238.     s1i = si->slist;
  239.     w = 0;
  240.     while (s1i->color) {
  241.         w += s1i->width*scale;
  242.         s1i++;
  243.     }
  244.     if (si->flags & SYM) {
  245.         w *= 2;
  246.         s1i--;        /* back up to last entry */
  247.         w -= s1i->width*scale;    /* it doesn't get doubled */
  248.         s1i = si->slist;    /* first entry */
  249.         w -= s1i->width*scale;    /* it doesn't get doubled */
  250.     }
  251.     return w;
  252. }
  253.  
  254. /* the redraw function creates a pixmap, draws the tartan into it, and
  255.  * makes that the window background pixmap.
  256.  * When we draw into a pixmap, we have to draw a larger area and then
  257.  * use the inside of it to avoid edge effects on the line drawing.
  258.  * The constant K indicates how much larger the area is.
  259.  */
  260. redraw()
  261. {
  262. #define K 20    /* kludge factor */
  263.     int w,h;
  264.     int d;
  265.     TartanInfo *ti;
  266.     Sinfo *si;
  267.     Pixmap newpix;
  268.     Pixmap newpixK;
  269.     Pixmap oldpix;
  270.  
  271.     d = DefaultDepthOfScreen(TScreen);
  272.     ti = curtartan;
  273.     if (!ti) return;
  274.     si = &(ti->hstripes);    /* do the horizontal stripes */
  275.     h = tartanSize(si);
  276.     si = &(ti->vstripes);    /* do vertical stripes */
  277.     if (si->flags & HVSAME)
  278.         w = h;
  279.     else
  280.         w = tartanSize(si);
  281.     newpix = XCreatePixmap(TDisplay,TWindow,w,h,d);
  282.     if (!newpix) {
  283.         Warn("error creating new pixmap");
  284.         return;
  285.     }
  286.     newpixK = XCreatePixmap(TDisplay,TWindow,w+K,h+K,d);
  287.     if (!newpix) {
  288.         Warn("error creating new pixmap");
  289.         return;
  290.     }
  291.     drwheight = h+K;
  292.     oldpix = TDrawable;
  293.     TDrawable = newpixK;
  294.     DrawTartan(0,0,w+K,h+K);
  295.     XSetFunction(TDisplay,Tgc,GXcopy);
  296.     XSetPlaneMask(TDisplay,Tgc,AllPlanes);
  297.     XCopyArea(TDisplay,newpixK,newpix,Tgc,K/2,K/2,w+K,h+K,0,0);
  298.         /* copy center portion into new pixmap */
  299.     XSetWindowBackgroundPixmap(TDisplay,TWindow,newpix);
  300.     XClearWindow(TDisplay,TWindow);        /* put up the new background */
  301.     XFreePixmap(TDisplay,newpixK);
  302.     if (oldpix)
  303.         XFreePixmap(TDisplay,oldpix);
  304.     TDrawable = newpix;    /* for possible use by setrootbg */
  305. }
  306.  
  307. /* end */
  308.